#[derive(Debug)]
enum PersonId {
    // 括号里是和携带的数据的类型
    Passport(u32),
    UUID(String),
    IndentityCard(u32, u32, u32),
}

struct Person {
    name: String,
    last_name: String,
    age: u32,
    id: PersonId,
}

impl Person {
    // associated function
    // 这种方法适用于构造方法
    fn new() -> Person {
        Person {
            name: "default".to_string(),
            last_name: "default".to_string(),
            age: 0,
            id: PersonId::UUID("865fbd57-64b6-4064-8207-2368ead0436e".to_string()),
        }
    }

    fn from(name: String, last_name: String, age: u32, id: PersonId) -> Person {
        Person {
            name,
            last_name,
            age,
            id,
        }
    }

    fn display(&self) {
        println!(
            "{} {} {} {:?}",
            self.name, self.last_name, self.age, self.id
        );
    }

    fn change_age(&mut self, new_age: u32) {
        self.age = new_age;
    }
}

/*
   感觉类似go的interface

   一组类型的通用接口。
   A trait就像数据类型可以实现的接口。
   当一个类型 实现一个特征，
   可以使用泛型将其抽象地视为该特征 或特质对象。
*/
trait Log {
    fn display_info(&self);
    // found the following associated functions;
    // to be used as methods, functions must have a `self` parameter
    // note: the candidate is defined in the trait `Log`
    // fn alert_something( ) {
    fn alert_something(&self) {
        println!("Default implementation~~~~~!")
    }
}
impl Log for Person {
    fn display_info(&self) {
        println!(
            "{} {} {} {:?}",
            self.name, self.last_name, self.age, self.id
        );
    }
}
struct Animal(String);
impl Log for Animal {
    fn display_info(&self) {
        println!("{}", self.0);
    }

    fn alert_something(&self) {
        println!("Animal implementation~~~~~!")
    }
}
fn main() {
    let mut p = Person::new();
    p.display_info();

    let animal = Animal("dog".to_string());
    animal.display_info();

    log_info_2(&animal);

    log_info(animal);
    log_info(p);
}

fn log_info(val: impl Log) {
    val.alert_something();
}

// 编译之后占空间更小,但是功能比较少
fn log_info_2(val: &dyn Log) {
    val.alert_something();
}
